from ui import ui
from PyQt5.QtWidgets import QApplication
import sys
import struct
from configobj import ConfigObj
from PyQt5.QtWidgets import QFileDialog
import time

FLASH_PAGE_COUNT = (128)
FLASH_PAGE_SIZE = (1024)
FLASH_TOTAL_SIZE = (FLASH_PAGE_COUNT * FLASH_PAGE_SIZE)
BOOT_CODE_SIZE = (20 * 1024)
MAC_PARA_SIZE = (1 * 1024)
PUBLIC_PARA_SIZE = (1 * 1024)
APP_PARA_SIZE = (1 * 1024)
FLASH_BASE = (0)
FLASH_BOOT_CODE = (FLASH_BASE)
FLASH_MODULE_PARA = (FLASH_BOOT_CODE + BOOT_CODE_SIZE)
FLASH_PUBLIC_PARA = (FLASH_MODULE_PARA + MAC_PARA_SIZE)
FLASH_APP_PARA = (FLASH_PUBLIC_PARA + PUBLIC_PARA_SIZE)
FLASH_APP = (FLASH_APP_PARA + APP_PARA_SIZE)
APP_VARSIONS_SIZE = 32

config = ConfigObj("cfg.ini", encoding='UTF8')

BOOT_FILE = 'boot_file'
APP_FILE = 'app_file'
MODULE_ID = "module_id"
PARAM0 = "param0"
PARAM1 = "param1"
PARAM2 = "param2"
PARAM3 = "param3"


class ModuleTool():
    def __init__(self):
        self.init_file_path()
        self.init_module_type()
        self.init_pararm()

    def get_cfg(self, name, default=''):
        if config.get(name):
            return config[name]
        else:
            config[name] = default
            config.write()
            return default

    def set_cfg(self, name, var):
        config[name] = var
        config.write()

    def init_file_path(self):
        self.boot_path = self.get_cfg(BOOT_FILE, './boot.bin')
        self.app_path = self.get_cfg(APP_FILE, './app.bin')
        ui.boot_path.setText(self.boot_path)
        ui.app_path.setText(self.app_path)
        ui.boot_file.clicked.connect(self.change_boot_file)
        ui.app_file.clicked.connect(self.change_app_file)
        ui.creat.clicked.connect(self.creat_file)

    def init_module_type(self):
        ui.module_id.setValue(int(self.get_cfg(MODULE_ID, "0")))
        ui.module_id.valueChanged.connect(self.save_param)

    def init_pararm(self):
        ui.param0.setValue(int(self.get_cfg(PARAM0, "0")))
        ui.param1.setValue(int(self.get_cfg(PARAM1, "0")))
        ui.param2.setValue(int(self.get_cfg(PARAM2, "0")))
        ui.param3.setValue(int(self.get_cfg(PARAM3, "0")))
        ui.param0.valueChanged.connect(self.save_param)
        ui.param1.valueChanged.connect(self.save_param)
        ui.param2.valueChanged.connect(self.save_param)
        ui.param3.valueChanged.connect(self.save_param)

    def save_param(self):
        self.set_cfg(PARAM0, ui.param0.value())
        self.set_cfg(PARAM1, ui.param1.value())
        self.set_cfg(PARAM2, ui.param2.value())
        self.set_cfg(PARAM3, ui.param3.value())
        self.set_cfg(MODULE_ID, ui.module_id.value())

    def change_boot_file(self):
        boot_path = QFileDialog.getOpenFileName(ui)
        boot_path = boot_path[0]
        if boot_path != '':
            self.boot_path = boot_path
            ui.boot_path.setText(self.boot_path)
            self.set_cfg(BOOT_FILE, self.boot_path)

    def change_app_file(self):
        app_path = QFileDialog.getOpenFileName(ui)
        app_path = app_path[0]
        if app_path != '':
            self.app_path = app_path
            ui.app_path.setText(self.app_path)
            self.set_cfg(APP_FILE, self.app_path)

    def load_boot_file(self):
        try:
            with open(self.boot_path, 'rb') as f:
                data = f.read()
                f.close()
                return data
        except:
            ui.msg("boot文件错误:{}".format(self.boot_path))
            return None

    def load_app_file(self):
        try:
            with open(self.app_path, 'rb') as f:
                data = f.read()
                f.close()
                return data
        except:
            ui.msg("app文件错误:{}".format(self.app_path))
            return None

    def encode_10_to_36(self, num, bit_num=1):
        encode = bytearray(bit_num)
        for i in range(bit_num):
            mod = num % 36
            if mod < 10:
                encode[bit_num - i - 1] = ord(str(int(mod)))
            else:
                encode[bit_num - i - 1] = ord('A') + (mod - 10)
            num //= 36
        return bytes(encode)

    def get_mac_info(self):
        module = ui.module_id.value()
        module_id = self.encode_10_to_36(module, 2)
        t = time.localtime()
        year = self.encode_10_to_36(t.tm_year - 2019)
        mon = self.encode_10_to_36(t.tm_mon)
        day = self.encode_10_to_36(t.tm_mday)
        hour = self.encode_10_to_36(t.tm_hour, 2)
        minute = self.encode_10_to_36(t.tm_min, 2)
        sec = self.encode_10_to_36(t.tm_sec, 2)
        random = self.encode_10_to_36(0, 4)
        int_random = 0  # 烧录器做了自动累加
        other_parm_0 = ui.param0.value()
        other_parm_1 = ui.param1.value()
        other_parm_2 = ui.param2.value()
        other_parm_3 = ui.param3.value()

        mac = struct.pack('2sccc2s2s2s4siiiii', module_id, year, mon, day,
                          hour, minute, sec, random, int_random,
                          other_parm_0, other_parm_1, other_parm_2,
                          other_parm_3)
        return mac

    def write_boot_file(self, file, boot):
        file.write(boot)

    def write_module_parm(self, file, mac):
        file.seek(FLASH_MODULE_PARA, 0)
        file.write(bytes([0xff for i in range(MAC_PARA_SIZE)]))
        file.seek(FLASH_MODULE_PARA, 0)
        file.write(mac)

    def write_public_parm(self, file):
        parm = bytes([0xff, 0xaa])
        file.seek(FLASH_PUBLIC_PARA, 0)
        file.write(bytes([0xff for i in range(MAC_PARA_SIZE)]))
        file.seek(FLASH_PUBLIC_PARA, 0)
        file.write(parm)

    def write_app_parm(self, file):
        parm = bytes([0xff for i in range(MAC_PARA_SIZE)])
        file.seek(FLASH_APP_PARA, 0)
        file.write(parm)

    def write_app_file(self, file, app):
        file.seek(FLASH_APP, 0)
        file.write(app)

    def creat_file(self):
        boot = self.load_boot_file()
        if boot is None:
            return
        app = self.load_app_file()
        if app is None:
            return
        mac = self.get_mac_info()
        if mac is None:
            return
        file_path = QFileDialog.getSaveFileName(ui)
        try:
            with open(file_path[0], 'wb') as f:
                self.write_boot_file(f, boot)
                self.write_module_parm(f, mac)
                self.write_public_parm(f)
                self.write_app_parm(f)
                self.write_app_file(f, app)
                f.close()
                ui.msg("Ok")
        except:
            ui.msg('Fail')

if __name__ == "__main__":
    ui.show()
    c = ModuleTool()
    sys.exit(ui.app.exec_())